// interface module, modified by regret
#ifndef INTERFACE_H
#define INTERFACE_H

// GameInp structure
#include "gameinp.h"

// Interface
#include "vid_filter.h"
#include "aud_audio.h"
#include "vid_video.h"
#include "inp_input.h"

// Macro for releasing a COM object
#define RELEASE(x) { if ((x)) (x)->Release(); (x) = NULL; }

// Interface info (used for all modules)
struct InterfaceInfo {
	const wchar_t* pszModuleName;
	wchar_t** ppszInterfaceSettings;
	wchar_t** ppszModuleSettings;

	// device info, added by regret
	unsigned int deviceNum;
	wchar_t** deviceName;
};

int IntInfoFree(InterfaceInfo* info);
int IntInfoInit(InterfaceInfo* info);
int IntInfoAddStringInterface(InterfaceInfo* info, wchar_t* str);
int IntInfoAddStringModule(InterfaceInfo* info, wchar_t* str);

// Input plugin:
class InputInterface {
public:
	const wchar_t* driver_list();
	void driver(const wchar_t* driver = L"");

	int init();
	int exit();
	int setCooperativeLevel(bool exclusive, bool foreGround);
	int make(bool copy);
	int find(int flags);
	int tick();
	int getControlName(int code, wchar_t* deviceName, wchar_t* controlName);
	InterfaceInfo* get();
	const wchar_t* getName();

	int getInpState(int code);
	int getInpGamepadAxis(int i, const int axis);
	int getInpMouseAxis(int i, const int axis);

	void term();
	int select(const wchar_t* driver);

	InputInterface() {
	}
	~InputInterface() {
		term();
	}

private:
	Input* p;
};

extern InputInterface inputInterface;	// input interface instance

extern bool inputOkay;
extern wchar_t inputSelect[16];

// Audio Output plugin
int audWriteSlience(int draw = 0);			// Write silence into the buffer

class AudioInterface {
public:
	int audVolume;				// Sound volume (% * 100)
	bool audPlaying;			// True if the Loop buffer is playing

	const wchar_t* driver_list();
	void driver(const wchar_t* driver = L"");

	int init();
	int exit();
	int play();
	int stop();
	int blank();
	int check();
	int setvolume(int vol);
	int set(int (*callback)(int));
	int setfps();

	void term();
	int select(const wchar_t* driver);
	InterfaceInfo* get();
	const wchar_t* getName();
	void setdevice(int device);
	int getdevice(const wchar_t* driver = NULL);

	AudioInterface() {
		audPlaying = false;
		audVolume = 10000;
	}
	~AudioInterface() {
		term();
	}

private:
	Audio* p;
};

extern AudioInterface audioInterface;	// audio interface instance

extern int audSampleRate;		// sample rate
extern int audSegCount;			// Segs in the pdsbLoop buffer
extern int audSegLen;			// Seg length in samples (calculated from Rate/Fps)
extern int audAllocSegLen;		// Allocated seg length in samples
extern short* audNextSound;		// The next sound seg we will add to the sample loop
extern bool audOkay;			// True if DSound was initted okay
extern int audDSPModule;		// DSP module to use: 0 = none, 1 = low-pass filter, 2 = reverb
extern int audStereoUpmixing;	// Enable stereo upmixing (XAudio2 only)
extern wchar_t audSelect[16];		// Which audio plugin is selected
extern int dsDevice;			// dsound device
extern int oalDevice;			// openal device
extern int xa2Device;			// xaudio2 device

// Video Output plugin
class VideoInterface {
public:
	const wchar_t* driver_list();
	void driver(const wchar_t* driver = L"");

	int init();
	int exit();
	int frame();
	int doframe(bool redraw);
	int paint(int validate);
	int redraw();
	int recalcPal();

	void term();
	int reinit();
	int scale(void* rect, unsigned width, unsigned height);
	int select(const wchar_t* driver);
	void clear();

	const wchar_t* getName();
	InterfaceInfo* get();
	int set(const wchar_t* name, const void* value);

	bool setGameInfo();

	void calcGameAspect();
	double getGameAspect() { return gameAspect; }

	bool allocVidImage();
	void freeVidImage();
	unsigned char* getVidImage() { return vidImage; }
	unsigned getImageWidth() { return imageWidth; }
	unsigned getImageHeight() { return imageHeight; }
	unsigned getImagePitch() { return imagePitch; }

	VideoInterface() {
		vidImage = fullImage = 0;
		gameAspect = (double)4 / (double)3;
		imageWidth = DEFAULT_IMAGE_WIDTH;
		imageHeight = DEFAULT_IMAGE_HEIGHT;
		imagePitch = 0;
	}
	~VideoInterface() {
		term();
	}

private:
	Video* p;

	unsigned char* vidImage;
	unsigned char* fullImage;
	double gameAspect;
	unsigned imageWidth, imageHeight;	// Memory buffer size
	unsigned imagePitch;				// Memory buffer pitch
};

extern VideoInterface videoInterface;	// video interface instance

#ifdef _WIN32
extern HWND hVidWnd;
#endif

extern bool vidOkay;
extern wchar_t vidSelect[16];
extern unsigned int vidWidth, vidHeight, vidDepth, vidRefresh;
extern unsigned int vidScrnWidth, vidScrnHeight, vidScrnDepth;
extern int vidFullscreen;
extern int vidCorrectAspect;
extern int vidFullStretch;
extern int vidRotationAdjust;
extern int vidTripleBuffer;
extern int vidVSync;

extern int vidScrnAspectX, vidScrnAspectY;
extern double vidScrnAspect;
extern bool vidAutoScrnAspect;
extern unsigned int vidAdapter;	// Which adapter device is selected

#endif
